﻿#include "ModbusTcpServer.h"
#include <QUrl>

ModbusTcpServer::ModbusTcpServer(QObject *parent)
    : PLCServerBase{parent}
{
    mServer = new QModbusTcpServer(this);
    connect(mServer, &QModbusServer::errorOccurred, this, [&](QModbusDevice::Error error){
        emit sigErrOccur(mConfig.name + mServer->errorString());
    });
    connect(mServer, &QModbusServer::stateChanged, this, [&](QModbusDevice::State state){
        if(state == QModbusDevice::ConnectedState){
            setServerState(CS_UnConnected);
        } else  if(state == QModbusDevice::UnconnectedState){
            setServerState(CS_Invalid);
        }
    });
    connect(mServer, &QModbusServer::dataWritten, this, &ModbusTcpServer::readData);

    connect(dynamic_cast<QModbusTcpServer*>(mServer), &QModbusTcpServer::modbusClientDisconnected,this,[&](QTcpSocket* client){
        emit sigMsg(("<font color=\'red\'>客户端断开连接</font>"));
    });

    //安装观察者对象，监控连接上的客户端
    observer = new ModbusTcpConnectionObserver;
    observer->setServer(this);
    dynamic_cast<QModbusTcpServer*>(mServer)->installConnectionObserver(observer);

}

void ModbusTcpServer::initCom()
{
    if (!mServer) {
        emit sigErrOccur(tr("Could not create Modbus server."));
    } else {
        if(mServer->state() == QModbusDevice::ConnectedState){
            mServer->disconnectDevice();
        }
        QModbusDataUnitMap reg;
        coilDataPre =  { QModbusDataUnit::Coils, 0, mConfig.addrCount };
        holdDataPre =  { QModbusDataUnit::DiscreteInputs, 0, mConfig.addrCount };
        discreDataPre =  { QModbusDataUnit::HoldingRegisters, 0, mConfig.addrCount};
        inputDataPre =  { QModbusDataUnit::InputRegisters, 0, mConfig.addrCount };
        reg.insert(QModbusDataUnit::Coils, coilDataPre);
        reg.insert(QModbusDataUnit::DiscreteInputs, discreDataPre);
        reg.insert(QModbusDataUnit::HoldingRegisters, holdDataPre);
        reg.insert(QModbusDataUnit::InputRegisters, inputDataPre);
        mServer->setMap(reg);

        //connect plc
        QString plc_address = mConfig.tcp.mLocalIP + ":" + QString::number(mConfig.tcp.mLocalPort);
        const QUrl url = QUrl::fromUserInput(plc_address);
        mServer->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());
        mServer->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());
        mServer->setServerAddress(mConfig.serverID);
        if (!mServer->connectDevice()) {
            emit sigMsg(tr("<font color=\'red\'>服务端连接失败 </font>") + mServer->errorString());
        }
    }
}

void ModbusTcpServer::onClientConnect(QString addr)
{
    setServerState(CS_Connected);
    setupDeviceData();
    emit sigMsg(("<font color=\'green\'>客户端连接成功</font>"));
}
